package reference;

import henry.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import reference.constant.RefConstant;
import reference.vo.ComponentVo;
import reference.vo.ReferenceVo;
import reference.vo.ReportVo;
import reference.vo.UieComponentVo;

import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author hujian
 * @date 2023/2/17 9:52
 * @description
 */
@Slf4j
public class Main {
    /**
     * 第一次全匹配
     */
    static final Pattern REF_CN_PATTERN = Pattern.compile("^\\[.{0,3}\\](?<authors>[\\u4e00-\\u9fff|,，, ]+)\\.\\s*(?<title>.*?)(?<type>\\[[A-Z]\\])\\s*\\.\\s*" +
            "(?<location>[^，]*?)：?(?<school>[^，,]*),?\\s*(?<year>\\d{4}),?(?<page>.*?)(?<endpoint>\\.)");
    /**
     * 第二次半匹配到类型
     */
    static final Pattern REF_BEFORE_TYPE_PATTERN = Pattern.compile("^\\[.{0,3}\\](?<authors>[\\u4e00-\\u9fff|,，, ]+)\\.\\s*(?<title>.*?)(?<type>\\[[A-Z]\\])");

    /**
     * 第三次仅匹配规范的类型
     */
    static final Pattern REF_BEFORE_TYPE_PATTERN2 = Pattern.compile(".*[\\u4e00-\\u9fff]{5}.*(?<type>\\[[A-Z]\\])");

    /**
     * 第四次匹配不规范的类型
     */
    static final Pattern REF_BEFORE_TYPE_PATTERN3 = Pattern.compile(".{10,}(?<type>[\\[［{〔【][^\\d\\u4e00-\\u9ef5]{1,3}[\\]】]?)");

    /**
     * 英文第一次半匹配到类型
     */
    static final Pattern REF_EN_TYPE_PATTERN = Pattern.compile("^\\[.{0,3}\\](?<authors>[a-zA-Z-,\\s]+\\s*\\.)\\s*(?<title>[a-zA-Z][\\w\\s,&/:⁃–'-]{10,})(?<type>\\[[A-Z]\\])");

    /**
     * 英文第二次仅匹配到规范的类型
     */
    static final Pattern REF_EN_TYPE_PATTERN1 = Pattern.compile("(?<beforeType>.*)(?<type>\\[[A-Z]\\])");

    public static void main(String[] args) throws IOException {

        String texts = "[1] 郭国庆.服务营销.5版.北京：中国人民大学出版社，2021.1\n" +
                "[2]郭国庆.服务营销.2版.北京：中国人民大学出版社，2019：77-80.\n" +
                "[3]Cardozo, Richard N. An Experimental Study of Customer Effort, Expectation, and Satisfaction[J].Journal of Marketing Research,1965,2(3):244-249.\n" +
                "[4]Howard J A, Sheth J N, Howard J A. The theory of buyer behavior[M].Wiley, 1969. \n" +
                "[5]Olshavsky & Miller,Customer Expectations,Product Performance,and Perceived Product Quality, Journal of Marketing Research,1972,9(2):19-21. \n" +
                "[6][10]Hunt H K.Conceptualization and measurement of consumer satisfaction and dissatisfaction [M].Cambridge MarketingInstitute,1977. \n" +
                "[7]Wilton and Emerging Prardigms for the Study of Consumer Satisfaction European Research,1988.(14):4-11\n" +
                "[8]Oliver,R.L.Satisfaction:A behavioral Perspective on the consumer[M].Irwin/Mc Graw-Hill,1997\n" +
                "[9]Kotler,Philip.Chapter6:Analyzing consumer markets and buyer behavior.[J].Marketing Management,1991: 161-192. \n" +
                "[10]Athanassopoulos,Antreas D.(2000),“Customers Satisfaction Cues to Support Market Segmentation and Explain Switching Behavior,”Journal of Business Research.47（3）191-207.\n" +
                "[11]Kotler，Management Analysis [J].Implementation and Control ,1999. \n" +
                "[12]Amornrat Pattarakitham A. The factors influence customer satisfaction and loyalty: A study of tea beverage in Bangkok[C]//XIV International Business and Economy Conference (IBEC) Bangkok, Thailand. 2015.\n" +
                "[13]王学斌.企业营销战略:关注消费者满意度与忠诚感[J]经济经纬,2000,(04):66 - 67\n" +
                "[14]刘宇.客户满意度测评方法的研究[M].数量经济技术经济研究，2001(2).\n" +
                "[15]宋先道，李涛.客户满意指数(CSI)研究现状分析及改进措施[J].武汉理工大学学报，2002(5).\n" +
                "[16]陆奇斌,赵平,王高,等.消费者满意度测量中的光环效应[J].心理学报，2005，37(4)：524-534. \n" +
                "[17]刘向阳，层次分析法原理[D].天津：天津大学出版社，2005.\n" +
                "[18]王祥翠.港口物流企业客户满意度研究[J].科技经济市场，2006，（12）：202.\n" +
                "[19]王静,刘玥.新式茶饮行业线下实体店客户满意度指标研究[J].市场研究,2019(07):10-12. DOI:10.13999/j.cnki.scyj.2019.07.003.\n" +
                "[20]吴天妹，卢黎莉.关于宁波市大学生一点点奶茶消费心理与行为的研究[J].中国商论，2019（21）：76-78.\n" +
                "[21]吴凡,张艳.基于奶茶消费者消费偏好的奶茶店营销策略分析[J].广西质量监督导报,2019(05):226+225.\n" +
                "[22]王淼灵.消费者心理对奶茶店市场竞争的影响[J].现代商贸工业,2020,41(18):34-36. DOI:10.19311/j.cnki.1672-3198.2020.18.018.\n" +
                "[23]王粲,姜棱炜.基于期望确认理论的南宁高校周边“蜜雪冰城”消费者满意度及影响因素研究[J].企业研究,2022(02):23-28.";
        List<String> refs = Arrays.asList(texts.split("\n"));

        ReportVo reportVo = checkRefsList(refs);


//        BufferedReader in = new BufferedReader(new FileReader("D:\\Projectspace\\python\\individual\\pythonProjects2\\file_parse\\ref2.txt"));
//        String str;
//        while ((str = in.readLine()) != null) {
//            if (str.contains("C:\\Users") || str.contains("参考文献")) {
//                continue;
//            }
//            checkThesisReference(str);
//        }
    }

    public static ReportVo checkRefsList(List<String> refs) {
        List<ReferenceVo> referenceVoList = new ArrayList<>();
        for (String ref : refs) {
            int cnLength = RefUtils.getCnTxt(ref).length();
            ReferenceVo referenceVo = new ReferenceVo();

            // TODO 前置处理
            // TODO 1 包含/OL的单独处理 (电子文献)
            // TODO 2 以汉字打头的单独处理
            // TODO 3 不以[序号]开头的单独处理
            // TODO 4 多个类型信息

            //带多个期刊信息的
            ref = ref.replace(" ", " ");

            if (cnLength > 10) {
                referenceVo.setLanguage(RefConstant.REF_CN);
                //76%的概率走到这里
                checkCnReference(referenceVo, ref);

                //TODO 中文后置处理
            } else if (cnLength == 0 && ref.length() > 50) {
                //24%的概率走到这里
                referenceVo.setLanguage(RefConstant.REF_EN);
                checkEnReference(referenceVo, ref);
                // 英文作者需要后校验出列表
                //TODO 英文后置处理
            } else {
                referenceVo.setLanguage(RefConstant.REF_OTHER);
                log.error("参考文献不规范,内容过短或者英文中出现汉字===> {}", ref);
                referenceVo.getErrorMsg().add(RefConstant.ERROR_LEVEL1_OTHER);
            }

            referenceVo.setSourceText(ref);
            System.out.println(ref);
            System.out.println("作者：" + referenceVo.getAuthors());
            System.out.println("标题：" + referenceVo.getTitle());
            System.out.println("类型：" + referenceVo.getType());
            System.out.println("地区：" + referenceVo.getLocation());
            System.out.println("机构：" + referenceVo.getSchool());
            System.out.println("年份：" + referenceVo.getYear());
            System.out.println("页码：" + referenceVo.getPage());
            System.out.println("其他：" + referenceVo.getOther());
            System.out.println(referenceVo.getErrorMsg());
            System.out.println("=========================================");
            referenceVoList.add(referenceVo);
        }
        ReportVo reportVo = new ReportVo();
        for (int i = 0; i < refs.size(); i++) {
            ReferenceVo referenceVo = referenceVoList.get(i);
            referenceVo.setNorm(referenceVo.getErrorMsg().size() <= 0);
            if (null == referenceVo.getType()) {
                reportVo.getLostType().add(i);
            } else {
                referenceVo.generateComponent(RefConstant.REF_TYPE, referenceVo.getType());
            }
            if (null != referenceVo.getLocation()) {
                referenceVo.generateComponent(RefConstant.REF_LOCATION, referenceVo.getLocation());
            }

            if (null == referenceVo.getAuthors()) {
                reportVo.getLostAuthor().add(i);
            } else {
                referenceVo.generateComponent(RefConstant.REF_AUTHOR, referenceVo.getAuthors());
            }
            if (null == referenceVo.getTitle()) {
                reportVo.getLostTitle().add(i);
            } else {
                referenceVo.generateComponent(RefConstant.REF_TITLE, referenceVo.getTitle());
            }
            if (null == referenceVo.getSchool()) {
                reportVo.getLostSchool().add(i);
            } else {
                referenceVo.generateComponent(RefConstant.REF_SCHOOL, referenceVo.getSchool());
            }
            if (null == referenceVo.getYear()) {
                reportVo.getLostYear().add(i);
            } else {
                referenceVo.generateComponent(RefConstant.REF_YEAR, referenceVo.getYear());
            }
            if (null == referenceVo.getPage()) {
                reportVo.getLostPage().add(i);
            } else {
                referenceVo.generateComponent(RefConstant.REF_PAGE, referenceVo.getPage());
            }
            //TODO 卷期暂时没有识别
//            if (null == referenceVo.getVolumePeriod()){
//                reportVo.getLostVolumePeriod().add(i);
//            }
            String year = referenceVo.getYear();
            if (null != year) {
                year = RefUtils.findPattern(referenceVo.getYear(), "[\\d]{4}");
            }
            if (null != year && (2023 - Integer.parseInt(year)) < 4) {
                reportVo.getRecentThreeYearIndices().add(i);
            }
            if (referenceVo.getLanguage().equals(RefConstant.REF_CN)) {
                reportVo.getCnIndices().add(i);
            } else if (referenceVo.getLanguage().equals(RefConstant.REF_EN)) {
                reportVo.getEnIndices().add(i);
            }
            //生成错误总结
            referenceVo.generateSummary(i);
            //生成规范格式的参考文献
//            referenceVo.generateSummary();
        }
        reportVo.setReferenceVoList(referenceVoList);
        return reportVo;
    }

    /**
     * 根据统计,英文参考文献 47% 是只包含3个小数点
     * 第一个小数点前是作者姓名
     * 第一个和第二个小数点中间是标题
     * 第二个小数点后是期刊,年份,页码等信息
     * 第三个小数点在最末尾
     */
    public static void checkEnReference(ReferenceVo referenceVo, String ref) {
        Matcher m = REF_EN_TYPE_PATTERN.matcher(ref);
        if (m.find()) {
            //35% 正常匹配到带类型的英文参考文献处
            log.info("第一次匹配到标准的带类型的参考文献");
            recordReference(referenceVo, m, 2);
            String afterType = ref.substring(m.end());
            checkEnAfterType(referenceVo, afterType);
        } else {
            Matcher m2 = REF_EN_TYPE_PATTERN1.matcher(ref);
            if (m2.find()) {
                //31% 仅匹配含类型的英文参考文献
                log.info("第二次校验,仅匹配标准类型");
                String beforeType = m2.group("beforeType");
                referenceVo.setType(m2.group("type"));
                //校验作者
                checkEnAuthor(referenceVo, beforeType);
                //校验类型后面的信息
                String afterTypeContent = ref.substring(m2.end());
                checkEnAfterType(referenceVo, afterTypeContent);
            } else {
                //37%没找到英文参考文献类型
                List<Integer> decimalPoints = RefUtils.findDecimalPoints(ref);
                if (decimalPoints.size() == 3) {
                    Pattern pattern = Pattern.compile("^\\[.{0,3}\\](?<authors>[a-zA-Z-,\\s]+\\s*\\.)[^a-zA-Z]*(?<title>[a-zA-Z][\\w\\s,&/:⁃–'-]{10,}[A-Za-z])[^a-zA-Z]*(?<school>[a-zA-Z][\\w\\s,&/:⁃–'-]{10,}[A-Za-z])");
                    Matcher m3 = pattern.matcher(ref);
                    int tmp;
                    if (m3.find()) {
                        log.info("第三次校验英文参考文献类型不规范,小数点数量为3,按正则切分!");
                        recordReference(referenceVo, m3, 3);
                        tmp = m3.end();
                    } else {
                        log.info("第三次校验英文参考文献类型不规范,小数点数量为3,按小数点切分!");
                        referenceVo.setAuthors(RefUtils.getEnAuthorSeq(ref.substring(0, decimalPoints.get(0))) + ".");
                        referenceVo.setTitle(RefUtils.getEnSeq(ref.substring(decimalPoints.get(0), decimalPoints.get(1))));
                        tmp = decimalPoints.get(1);
                    }
                    checkEnAfterType(referenceVo, ref.substring(tmp));
                } else {
                    log.info("第四次校验英文使用uie识别");
                    checkEnByUie(referenceVo, ref, false);
                }
            }
        }
    }

    public static void checkCnReference(ReferenceVo referenceVo, String ref) {
        Matcher m = REF_CN_PATTERN.matcher(ref);
        if (RefUtils.countPattern(ref, "\\[[A-Z]\\]") > 1) {
            referenceVo.getErrorMsg().add(RefConstant.ERROR_LEVEL1_TYPE);

        } else {
            // 开始识别
            if (m.matches()) {
                // 全匹配了,直接获取各个内容的信息
                // 40%的概率走到这里
                log.info("第一次校验,全匹配");
                recordReference(referenceVo, m, 1);
            } else {
                Matcher m2 = REF_BEFORE_TYPE_PATTERN.matcher(ref);
                if (m2.find()) {
                    // 12%的概率走到这里
                    log.info("第二次校验,半匹配到类型");
                    recordReference(referenceVo, m2, 2);
                    //解析类型[D]后面的内容
                    String afterTypeContent = ref.substring(m2.end());
                    checkAfterType(referenceVo, afterTypeContent);
                } else {
                    Matcher m3 = REF_BEFORE_TYPE_PATTERN2.matcher(ref);
                    if (m3.find()) {
                        log.info("第三次校验,匹配到规范的类型信息");
                        //10% 的概率走到这里
                        //使用uie识别到作者
                        String beforeType = m3.group(0);
                        referenceVo.setType(m3.group("type"));
                        //校验作者
                        List<UieComponentVo> uieTitleInfo = UieUtil.getOneUieAuthorInfo(beforeType);
                        checkAuthor(referenceVo, uieTitleInfo, beforeType);
                        //校验类型后面的信息
                        String afterTypeContent = ref.substring(m3.end());
                        checkAfterType(referenceVo, afterTypeContent);
                    } else {
                        // 4%的概率走到这里
                        Matcher m4 = REF_BEFORE_TYPE_PATTERN3.matcher(ref);
                        if (m4.find()) {
                            log.info("第四次校验,匹配到不规范的类型信息");
                            System.out.println(m4.group());
                            System.out.println(m4.group("type"));
                            String mayBeType = m4.group("type");
                            if (RefUtils.hasDBC(mayBeType)) {
                                mayBeType = RefUtils.toDBC(mayBeType);
                                referenceVo.getErrorMsg().add(RefConstant.ERROR_TYPE);
                            }
                            String enTxt = RefUtils.getEnTxt(mayBeType);
                            if (enTxt.length() == 1) {
                                referenceVo.setType(mayBeType);
                            } else {
                                referenceVo.getErrorMsg().add(RefConstant.ERROR_TYPE1);
                            }
                            String text = m4.group(0);
                            //校验作者
                            List<UieComponentVo> uieTitleInfo = UieUtil.getOneUieAuthorInfo(text);
                            checkAuthor(referenceVo, uieTitleInfo, text);
                            //解析类型[D]后面的内容
                            String afterTypeContent = ref.substring(m4.end());
                            checkAfterType(referenceVo, afterTypeContent);
                        } else {
                            // 10%的概率走到这里
                            referenceVo.getErrorMsg().add(RefConstant.ERROR_LEVEL1_TYPE1);
                            List<UieComponentVo> books = RefUtils.getBooks(ref);
                            List<UieComponentVo> oneUieAuthorInfo = UieUtil.getOneUieAuthorInfo(ref);
                            int authorStart = oneUieAuthorInfo.size() > 0 ? oneUieAuthorInfo.get(0).getStart() : 0;
                            if (oneUieAuthorInfo.size() > 0) {
                                String substring = ref.substring(0, authorStart);
                                String maybeTitleSeq = RefUtils.getCnSeq(substring);
                                //可能存在作者写在标题后面的不规范情况
                                if (null != maybeTitleSeq && maybeTitleSeq.length() > 5) {
                                    referenceVo.setTitle(maybeTitleSeq);
                                    checkYear(referenceVo, ref.substring(oneUieAuthorInfo.get(oneUieAuthorInfo.size() - 1).getEnd()));
                                    referenceVo.getErrorMsg().add(RefConstant.ERROR_LOST_AUTHOR1);
                                }
                            }

                            if (books.size() > 0) {
                                // 5%存在书名号的情况
                                log.info("第五次校验,处理带书名号的数据");
                                // TODO 建议补充书籍类型信息
                                if (books.size() == 1 && null == referenceVo.getTitle()) {
                                    referenceVo.setTitle(books.get(0).getText());
                                    checkYear(referenceVo, ref.substring(books.get(0).getEnd()));
                                } else if (books.size() == 2) {
                                    referenceVo.setTitle(books.get(0).getText());
                                    referenceVo.setSchool(books.get(1).getText());
                                    checkYear(referenceVo, ref.substring(books.get(1).getEnd()));
                                }

                                //处理姓名,第一个姓名是作者,在书名号后的姓名是译者
                                int start = books.get(0).getStart();
                                int end = books.get(books.size() - 1).getEnd();
                                for (UieComponentVo authorVo : oneUieAuthorInfo) {
                                    if (authorVo.getEnd() < start) {
                                        //著者
                                        referenceVo.getAuthorList().add(authorVo.getText());
                                    } else if (authorVo.getStart() > end) {
                                        //译者
                                        referenceVo.getTranslatorList().add(authorVo.getText());
                                    }
                                }
                                checkYear(referenceVo, ref.substring(end));
                            } else {
                                //5%没有书名号,没有类型的情况
                                log.info("第六次校验,使用uie进行识别");
                                List<String> texts = new ArrayList<>();
                                texts.add(ref);
                                List<Map<String, List<UieComponentVo>>> uieExtractMapList = UieUtil.getUieExtractMap(texts);
                                if (null != uieExtractMapList && uieExtractMapList.size() > 0) {
                                    //TODO 暂时只取第一个,后期可以做批量请求优化性能
                                    Map<String, List<UieComponentVo>> refInfoListMap = uieExtractMapList.get(0);
                                    if (refInfoListMap.containsKey("authors")) {
                                        checkAuthor(referenceVo, refInfoListMap.get("authors"), texts.get(0));
                                    } else {
                                        referenceVo.getErrorMsg().add(RefConstant.ERROR_LOST_AUTHOR);
                                    }
                                    int titleEnd = 0;
                                    if (refInfoListMap.containsKey("title")) {
                                        titleEnd = refInfoListMap.get("title").get(0).getEnd();
                                        referenceVo.setTitle(refInfoListMap.get("title").get(0).getText());
                                    } else if (null == referenceVo.getTitle()) {
                                        referenceVo.getErrorMsg().add(RefConstant.ERROR_LOST_TITLE);
                                    }
                                    if (refInfoListMap.containsKey("year")) {
                                        referenceVo.setYear(refInfoListMap.get("year").get(0).getText());

                                        Pattern p1 = Pattern.compile("(?<year>(20|19)\\d{2}[\\.-]?[\\d]{0,2}[-\\.]?\\d{0,2})");
                                        int yearEnd = refInfoListMap.get("year").get(0).getEnd();
                                        Matcher m5 = p1.matcher(ref);
                                        if (m5.find()) {
                                            referenceVo.setYear(m5.group());
                                            yearEnd = m5.end();
                                        }
                                        checkPageAfterYear(referenceVo, ref.substring(yearEnd));
                                    } else {
                                        referenceVo.getErrorMsg().add(RefConstant.ERROR_LOST_YEAR);
                                    }
                                    if (refInfoListMap.containsKey("school")) {
                                        referenceVo.setSchool(refInfoListMap.get("school").get(0).getText());
                                    } else {
                                        checkSchool(referenceVo, ref.substring(titleEnd));
                                        if (null == referenceVo.getSchool()) {
                                            referenceVo.getErrorMsg().add(RefConstant.ERROR_LOST_SCHOOL);
                                        }
                                    }

                                } else {
                                    //什么也没有识别到,这个可能是解析错误,不是参考文献。
                                    log.error("无法识别到任何有效的信息");
                                    referenceVo.getErrorMsg().add(RefConstant.ERROR_LEVEL1_OTHER);
                                }
                            }

                        }
                    }
                }
            }
        }
        //TODO 后校验
        if (referenceVo.getAuthorList().size() > 0 && null == referenceVo.getAuthors()) {
            referenceVo.setAuthors(String.join(",", referenceVo.getAuthorList()));
        }
    }

    private static void recordReference(ReferenceVo referenceVo, Matcher m, int version) {

        switch (version) {
            case 1:
                referenceVo.setAuthors(m.group("authors"));
                referenceVo.setTitle(m.group("title"));
                referenceVo.setType(m.group("type"));
                referenceVo.setLocation(m.group("location"));
                referenceVo.setSchool(m.group("school"));
                referenceVo.setYear(m.group("year"));
                String page = m.group("page");
                String endpoint = m.group("endpoint");
                String other = "";
                if (page.contains(".")) {
                    int find = page.indexOf(".");
                    if (find != -1) {
                        other = page.substring(find + 1);
                        page = page.substring(0, find);
                        if (null != endpoint) {
                            other = other + endpoint;
                        }
                    }
                }
                checkPageAfterYear(referenceVo, page);
                referenceVo.setOther(other);
                break;
            case 2:
                referenceVo.setAuthors(m.group("authors"));
                referenceVo.setTitle(m.group("title"));
                referenceVo.setType(m.group("type"));
                break;
            case 3:
                referenceVo.setAuthors(m.group("authors"));
                referenceVo.setTitle(m.group("title"));
                referenceVo.setSchool(m.group("school"));
                break;
        }
    }

    /**
     * ===================================校验中文参考文献=========================================
     */

    private static void checkAfterType(ReferenceVo referenceVo, String afterTypeContent) {
        if (RefUtils.hasDBC(afterTypeContent)) {
            referenceVo.getErrorMsg().add(RefConstant.ERROR_YEAR_PAGE1);
            afterTypeContent = RefUtils.toDBC(afterTypeContent);
        }
        Matcher m1 = Pattern.compile("(?<year>\\d{4})").matcher(afterTypeContent);
        if (m1.find()) {
            String afterYear = afterTypeContent.substring(m1.start());
            //判断年份之后的内容
            if (afterYear.length() - 4 < 2) {
                referenceVo.setYear(m1.group());
                referenceVo.getErrorMsg().add(RefConstant.ERROR_LOST_PAGE);
            } else {
                Pattern pattern = Pattern.compile("(?<year>(20|19)\\d{2}[\\.-]?[\\d]{0,2}[-\\.]?\\d{0,2})");
                Matcher matcher = pattern.matcher(afterYear);
                if (matcher.find()) {
                    //TODO 校验中间不规范的分隔符
                    referenceVo.setYear(matcher.group("year"));
                    checkPageAfterYear(referenceVo, afterTypeContent.substring(matcher.end()));
                } else {
                    referenceVo.setOther(afterYear);
                    //TODO 找出不规范的地方
                    referenceVo.getErrorMsg().add(RefConstant.ERROR_YEAR_PAGE);
                    System.out.println("=======>年份页码信息不规范1：" + afterYear);
                }
            }
            // 截取类型到年份之间的内容
            String text = afterTypeContent.substring(0, m1.start());
            List<ComponentVo> componentVos = RefUtils.getComponentVo(text);
            if (componentVos.size() == 1) {
                referenceVo.setSchool(componentVos.get(0).getText());
            } else if (componentVos.size() == 2) {
                referenceVo.setLocation(componentVos.get(0).getText());
                referenceVo.setSchool(componentVos.get(1).getText());
            } else {
                //TODO 找出不规范的地方
                referenceVo.getErrorMsg().add(RefConstant.ERROR_LOCATION_SCHOOL);
            }
        }
    }

    private static void checkAuthor(ReferenceVo referenceVo, List<UieComponentVo> uieTitleInfo, String text) {
        if (null == uieTitleInfo || uieTitleInfo.size() == 0) {
            referenceVo.getErrorMsg().add(RefConstant.ERROR_LOST_AUTHOR);
        } else {
            UieComponentVo first = uieTitleInfo.get(0);
            if (uieTitleInfo.size() == 1) {
                // 只有一个作者
                referenceVo.setAuthors(first.getText());
                int end = first.getEnd();
                referenceVo.setTitle(RefUtils.getTitle(text.substring(end)));
            } else {
                // 多个作者
                int start = uieTitleInfo.stream().map(UieComponentVo::getStart).min(Comparator.comparing(x -> x)).orElse(null);
                int end = uieTitleInfo.stream().map(UieComponentVo::getEnd).max(Comparator.comparing(x -> x)).orElse(text.length());
                referenceVo.setAuthors(text.substring(start, end));
                referenceVo.setTitle(RefUtils.getTitle(text.substring(end)));
                //TODO 校验作者之间的符号
            }
        }
    }

    private static void checkYear(ReferenceVo referenceVo, String text) {
        Pattern p1 = Pattern.compile(".*(?<year>(20|19)\\d{2}[\\.-]?[\\d]{0,2}[-\\.]?\\d{0,2})"); // 匹配整个字符串，并获取最后一个满足条件的年份
        Matcher m1 = p1.matcher(text);
        if (m1.find()) {
            String year = m1.group("year"); // 获取捕获组中的年份
            referenceVo.setYear(year);
            checkSchool(referenceVo, text);
            //往后获取页码信息
            if (null == referenceVo.getPage()) {
                Pattern p3 = Pattern.compile("(?<year>(20|19)\\d{2}[\\.-]?[\\d]{0,2}[-\\.]?\\d{0,2}).*(?<page>第[\\d一二三四五六七八九\\s-]{0,8}页)");
                Matcher m3 = p3.matcher(text);
                if (m3.find()) {
                    referenceVo.setPage(m3.group("page"));
                }
            }
        } else {
            referenceVo.getErrorMsg().add(RefConstant.ERROR_LOST_YEAR);
        }
    }

    private static void checkPageAfterYear(ReferenceVo referenceVo, String text) {
        if (null == referenceVo.getPage()) {
            Pattern p = Pattern.compile("(?<page>第?[\\d一二三四五六七八九\\s-]{0,8}\\d{1,4}[-\\+]\\d{1,4}页?)");
            Matcher m = p.matcher(text);
            if (m.find()) {
                referenceVo.setPage(m.group("page"));
            }
        }

    }

    private static void checkSchool(ReferenceVo referenceVo, String text) {
        //往前获取结构信息
        if (null == referenceVo.getSchool()) {
            Pattern p2 = Pattern.compile("(?<school>[\\u4e00-\\u9ef5]+).{0,5}(?<year>(20|19)\\d{2})");
            Matcher m2 = p2.matcher(text);
            if (m2.find()) {
                if (text.contains("《") || text.contains("》")) {
                    referenceVo.setSchool("《" + m2.group("school") + "》");
                } else {
                    referenceVo.setSchool(m2.group("school"));
                }
            }
        }
    }

    /**
     * ===================================校验英文参考文献=========================================
     */

    private static void checkEnAfterType(ReferenceVo referenceVo, String afterTypeContent) {
        if (RefUtils.hasDBC(afterTypeContent)) {
            referenceVo.getErrorMsg().add(RefConstant.ERROR_YEAR_PAGE1);
            afterTypeContent = RefUtils.toDBC(afterTypeContent);
        }
        Matcher m1 = Pattern.compile("(?<year>(20|19)\\d{2})").matcher(afterTypeContent);
        if (m1.find()) {
            String afterYear = afterTypeContent.substring(m1.end());
            referenceVo.setYear(m1.group());
            //判断年份之后的内容
            if (afterYear.length() < 2) {
                referenceVo.getErrorMsg().add(RefConstant.ERROR_LOST_PAGE);
            } else {
                //找页码信息
                //TODO 页码的识别可能还需要优化,没有-的情况的处理
                Pattern pattern = Pattern.compile("(?<phase>[(\\d)]*):?\\s*(?<page>\\d{1,4}[\\s–-]+\\d{1,4})");
                Matcher matcher = pattern.matcher(afterYear);
                if (matcher.find() && null != matcher.group("page")) {
                    //TODO 校验中间不规范的分隔符
                    referenceVo.setPage(matcher.group("page"));
                } else {
                    if (afterYear.contains("(") || afterYear.contains(")")) {
                        referenceVo.setOther(afterYear);
                        //TODO 找出不规范的地方
                        referenceVo.getErrorMsg().add(RefConstant.ERROR_LOST_PAGE);
                    } else {
                        Pattern pattern1 = Pattern.compile("(?<page>[\\d]+)");
                        Matcher m2 = pattern1.matcher(afterYear);
                        if (m2.find()) {
                            referenceVo.setPage(m2.group("page"));
                        } else {
                            referenceVo.getErrorMsg().add(RefConstant.ERROR_LOST_PAGE);
                        }
                    }
                }
            }
            // 2、截取类型到年份之间的内容做为出版机构
            if (null == referenceVo.getSchool()) {
                String text = afterTypeContent.substring(0, m1.start());
                String enSeq = RefUtils.getEnSeq(text);
                if (null != enSeq) {
                    referenceVo.setSchool(enSeq);
                } else {
                    //TODO 找出不规范的地方
                    referenceVo.getErrorMsg().add(RefConstant.ERROR_LOCATION_SCHOOL);
                    System.out.println("======>收录信息异常或缺失！");
                }
            }
        } else {
            referenceVo.getErrorMsg().add(RefConstant.ERROR_LOST_YEAR);
            //找页码信息
            checkPageAfterYear(referenceVo, afterTypeContent);
        }
    }

    private static void checkEnAuthor(ReferenceVo referenceVo, String beforeType) {
        List<Integer> decimalPoints = RefUtils.findDecimalPoints(beforeType);
        // 找作者和标题的分隔符
        int split = 0;
        if (decimalPoints.size() == 1) {
            split = decimalPoints.get(0);
        } else if (decimalPoints.size() > 1) {
            for (int i = decimalPoints.size() - 1; i > -1; i--) {
                // 从后往前找
                if (beforeType.length() - decimalPoints.get(i) < 5) {
                    continue;
                }
                split = decimalPoints.get(i);
                break;
            }
        } else {
            checkEnByUie(referenceVo, beforeType, true);
            referenceVo.getErrorMsg().add(RefConstant.ERROR_EN_AUTHOR_TITLE);
        }
        if (split > 0) {
            referenceVo.setAuthors(RefUtils.getEnAuthorSeq(beforeType.substring(0, split + 1)) + ".");
            referenceVo.setTitle(RefUtils.getEnSeq(beforeType.substring(split + 1)));
        }
    }

    private static void checkEnByUie(ReferenceVo referenceVo, String ref, boolean beforeType) {
        List<String> texts = new ArrayList<>();
        texts.add(ref);
        List<Map<String, List<UieComponentVo>>> uieExtractMapList = UieUtil.getEnUieExtractMap(texts);
        if (null != uieExtractMapList && uieExtractMapList.size() > 0) {
            //TODO 暂时只取第一个,后期可以做批量请求优化性能
            Map<String, List<UieComponentVo>> refInfoListMap = uieExtractMapList.get(0);
            int authorStart = 0, authorEnd = 0;
            if (refInfoListMap.containsKey("authors")) {
                List<UieComponentVo> authors = refInfoListMap.get("authors");
                if (null == referenceVo.getAuthors()) {
                    if (authors.get(0).getProbability() > 0.65) {
                        referenceVo.setAuthors(authors.get(0).getText());
                        authorStart = authors.get(0).getStart();
                        authorEnd = authors.get(0).getEnd();
                    }
                }
            } else {
                referenceVo.getErrorMsg().add(RefConstant.ERROR_EN_AUTHOR_TITLE);
            }
            int yearStart = 0;
            if (refInfoListMap.containsKey("title")) {
                yearStart = refInfoListMap.get("title").get(0).getEnd();
                if (null == referenceVo.getTitle()) {
                    String title = refInfoListMap.get("title").get(0).getText();
                    if (authorStart == refInfoListMap.get("title").get(0).getStart()) {
                        title = ref.substring(authorEnd, refInfoListMap.get("title").get(0).getEnd());
                        title = RefUtils.getEnSeq(title);
                    }
                    referenceVo.setTitle(title);
                }
            } else {
                //手动检查标题
                if (authorEnd > 0) {
                    //默认外文书名一般不含其它符号
                    if (refInfoListMap.containsKey("school")) {
                        if (null == referenceVo.getTitle()) {
                            referenceVo.setTitle(RefUtils.getEnSeq(ref.substring(authorEnd, refInfoListMap.get("school").get(0).getStart())));
                        }
                    }
                } else {
                    referenceVo.getErrorMsg().add(RefConstant.ERROR_LOST_TITLE);
                }
            }
            if (!beforeType) {
                if (refInfoListMap.containsKey("school")) {
                    if (null == referenceVo.getSchool()) {
                        referenceVo.setSchool(refInfoListMap.get("school").get(0).getText());
                    }
                    yearStart = refInfoListMap.get("school").get(0).getStart();
                } else {

                    if (null == referenceVo.getSchool()) {
                        referenceVo.getErrorMsg().add(RefConstant.ERROR_LOST_SCHOOL);
                    }
                }
                //处理年份
                if (null == referenceVo.getYear()) {
                    checkEnAfterType(referenceVo, ref.substring(yearStart));
                }
            }
        } else {
            //什么也没有识别到,这个可能是解析错误,不是参考文献。
            log.error("无法识别到任何有效的信息");
            referenceVo.getErrorMsg().add(RefConstant.ERROR_LEVEL1_OTHER);
        }
    }
}
